package com.solome.vertx;

import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;

import com.solome.vertx.annotation.RequestMapping;

import cn.hutool.core.util.ClassUtil;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

/**
 * 使用Vert.x实现一个简易HTTP服务器单例，管理HttpAction及其注解（如RequestMapping/Mapping）。 A
 * singleton class using Vert.x to implement a simple HTTP server, managing
 * HttpAction and its annotations (e.g., RequestMapping/Mapping).
 */
@Slf4j
public enum StartVertx {
	ins; // 单例实例 / Singleton instance

	// Vert.x实例 / Vert.x instance
	@Getter
	private Vertx vertx;

	// 默认配置参数 / Default configuration parameters
	// 设置Event Loop线程池大小，默认为可用处理器数的2倍
	// Sets the Event Loop thread pool size, default is 2 * available processors
	public int pollSizeEventLoop = 2 * Runtime.getRuntime().availableProcessors();

	// 设置Worker线程池最大大小，优化为256（默认20可能不足）
	// Sets the maximum Worker thread pool size, optimized to 256 (default 20 may be
	// insufficient)
	public int pollSizeEventWorker = 256;

	// 设置内部阻塞线程池最大大小，优化为256
	// Sets the internal blocking thread pool size, optimized to 256
	public int pollSizeInternalBlocking = 256;

	// 是否启用Vert.x集群模式，默认false
	// Whether to enable Vert.x cluster mode, default is false
	public boolean clusterEnabled = false;

	// 【集群模式】集群主机名，默认"localhost"
	// [Cluster mode] Cluster hostname, default "localhost"
	public String clusterHost = "localhost";

	// 【集群模式】集群端口，默认3000（优化为固定端口，避免随机）
	// [Cluster mode] Cluster port, default 3000 (optimized to fixed port, avoiding
	// random)
	public int clusterPort = 3000;

	// 【集群模式】ping检测间隔，默认10秒（单位ms）
	// [Cluster mode] Ping check interval, default 10 seconds (in ms)
	public int clusterPingInterval = 10_000;

	// 【集群模式】ping响应间隔，默认10秒（单位ms）
	// [Cluster mode] Ping reply interval, default 10 seconds (in ms)
	public int clusterPingReplyInterval = 10_000;

	// 阻塞线程检查间隔，默认10秒（单位ms）
	// Blocked thread check interval, default 10 seconds (in ms)
	public int blockingThreadCheckInterval = 10_000;

	// Event Loop最大执行时间，默认60秒（单位ns）
	// Maximum Event Loop execution time, default 60 seconds (in ns)
	public long executeTimeMaxEventLoop = 60_000_000_000L;

	// Worker线程最大执行时间，默认600秒（单位ns）
	// Maximum Worker thread execution time, default 600 seconds (in ns)
	public long executeTimeMaxWorker = 600_000_000_000L;

	// 是否启用高可用（HA）模式，默认false
	// Whether to enable High Availability (HA) mode, default false
	public boolean haEnabled = false;

	// 【HA模式】HA组名，默认"__DEFAULT__"
	// [HA mode] HA group name, default "__DEFAULT__"
	public String haGroup = "__DEFAULT__";

	// 【HA模式】仲裁节点数量，默认1
	// [HA mode] Quorum size, default 1
	public int quorumSize = 1;

	// 线程阻塞警告阈值，默认5秒（单位ns）
	// Thread blocking warning threshold, default 5 seconds (in ns)
	public long warningExceptionTime = 5_000_000_000L;

	// 存储HttpAction实例的线程安全映射，按路径排序
	// Thread-safe map storing HttpAction instances, sorted by path
	@Getter
	private final Map<String, HttpAction> actions = new TreeMap<>();

	// HTTP服务器端口，默认8080
	// HTTP server port, default 8080
	@Getter
	private int port = 8080;

	/**
	 * 加载指定包下的HttpAction类，通过注解扫描。 Loads HttpAction classes from the specified
	 * package via annotation scanning.
	 * 
	 * @param packageName 要扫描的包名 / Package name to scan
	 * @throws Exception 如果加载失败 / If loading fails
	 */
	private void loadPackage(String packageName) throws Exception {
		// 扫描带有RequestMapping注解的类
		// Scan classes with RequestMapping annotation
		Set<Class<?>> scans = ClassUtil.scanPackageByAnnotation(packageName, RequestMapping.class);
		for (Class<?> clazz : scans) {
			// 跳过接口和非HttpAction子类
			// Skip interfaces and non-HttpAction subclasses
			if (clazz.isInterface() || clazz.getSuperclass() != HttpAction.class) {
				continue;
			}

			// 获取RequestMapping注解并实例化HttpAction
			// Get RequestMapping annotation and instantiate HttpAction
			RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class);
			if (Objects.isNull(requestMapping)) {
				continue;
			}
			Constructor<?> constructor = clazz.getDeclaredConstructor();
			constructor.setAccessible(true); // 确保构造函数可访问 / Ensure constructor is accessible
			HttpAction action = (HttpAction) constructor.newInstance();
			action.setVertx(vertx);
			action.loadCache();

//			action.setRouter(path);

			// 注册所有缓存的路由
			// Register all cached routes
			for (Map.Entry<String, RequestCache> entry : action.getCache().entrySet()) {
				String fullPath = action.getRouter() + entry.getKey();
				actions.put(fullPath, action);
				if (requestMapping.log()) {
					log.info("注册路由 / Registered route: {} -> {}", action.getRouter() + entry.getKey().split("_")[0],
							entry.getValue().getMethod());
				}
			}
		}
	}

	/**
	 * 启动Vert.x HTTP服务器。 Starts the Vert.x HTTP server.
	 * 
	 * @param packageName 要扫描的包名 / Package name to scan
	 * @param port        监听端口 / Port to listen on
	 * @throws Exception 如果启动失败 / If startup fails
	 */
	public void start(String packageName, int port) throws Exception {
		this.port = port;

		// 配置Vert.x选项
		// Configure Vert.x options
		VertxOptions options = new VertxOptions().setEventLoopPoolSize(pollSizeEventLoop)
				.setWorkerPoolSize(pollSizeEventWorker).setInternalBlockingPoolSize(pollSizeInternalBlocking)
				.setBlockedThreadCheckInterval(blockingThreadCheckInterval)
				.setMaxEventLoopExecuteTime(executeTimeMaxEventLoop).setMaxWorkerExecuteTime(executeTimeMaxWorker)
				.setHAEnabled(haEnabled).setHAGroup(haGroup).setQuorumSize(quorumSize)
				.setWarningExceptionTime(warningExceptionTime);

		// 如果启用集群模式，配置集群参数
		// If cluster mode is enabled, configure cluster parameters
//        if (clusterEnabled) {
//            options.setClustered(true)
//                   .setClusterHost(clusterHost)
//                   .setClusterPort(clusterPort)
//                   .setClusterPingInterval(clusterPingInterval)
//                   .setClusterPingReplyInterval(clusterPingReplyInterval);
//        }

		// 创建Vert.x实例并部署Verticle
		// Create Vert.x instance and deploy Verticle
		vertx = Vertx.vertx(options);
		loadPackage(packageName);
		Future<String> deployment = vertx.deployVerticle(VerticleEngine.class.getName(), readOpts());

		// 处理部署结果
		// Handle deployment result
		deployment.onSuccess(v -> log.info(">> 启动Web服务于端口 / Start web service on port: {}", this.port))
				.onFailure(t -> log.error(">> 启动服务失败 / Start service failed: {}", t.getMessage(), t));
	}

	/**
	 * 创建Verticle部署选项。 Creates deployment options for Verticle.
	 * 
	 * @return 部署选项 / Deployment options
	 */
	public DeploymentOptions readOpts() {
		return new DeploymentOptions().setHa(haEnabled) // 支持HA / Enable HA
				.setInstances(pollSizeEventLoop) // Event Loop实例数 / Number of Event Loop instances
				.setWorkerPoolName("OptionsWorkerPool") // Worker池名称 / Worker pool name
				.setWorkerPoolSize(pollSizeEventWorker); // Worker池大小 / Worker pool size
	}

	/**
	 * 创建Worker Verticle部署选项（未使用，可选）。 Creates deployment options for Worker Verticle
	 * (unused, optional).
	 * 
	 * @return 部署选项 / Deployment options
	 */
	public DeploymentOptions readWorkerOpts() {
		return new DeploymentOptions().setHa(haEnabled).setInstances(pollSizeEventLoop)
				.setWorkerPoolName("WorkOptionsWorkerPool").setWorkerPoolSize(pollSizeEventWorker);
	}
}